/***************************************************************************
 *   Copyright (C) 2008 by joker   *
 *   joker@arcturus.pet.cyric.tohoku.ac.jp   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

//
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <time.h>
#include <md5.h>

//
#include <machine/param.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define BUFSIZE 512
#define SHMSZ 1024*1024*1024
#define SHMSZG 4

//#define SHMF "/home/joker/recon"
char *shmf0;
int shmkey=0;
int shmid=0;
unsigned char *shmdata=0;

int open_shm ( char *shmf, bool *first ) {
	int flg;
char str[128];
size_t s;
	shmf0=shmf;
if(first!=0) *first=false;
	if ( ( shmkey = ftok ( shmf, 'R' ) ) == -1 ) {
		perror ( "ftok" );
		return 1;
	}

	/* Create the segment. */
	flg= 0666;
	s=SHMSZ;
	s*=SHMSZG;
	if ( ( shmid = shmget ( shmkey, s, flg ) ) < 0 ) {
		flg= ( IPC_CREAT | 0666 );
		if ( ( shmid = shmget ( shmkey, s, flg ) ) < 0 ) {
			perror ( "shmget" );
			return 1;
		}else{
		if(first!=0) *first=true;
		}
	}
	sprintf(str,"%d",shmkey);
	setenv("RP3SHMKEY",str,1);
	sprintf(str,"%d",shmid);	
	setenv("RP3SHMID",str,1);

	/* attach the segment to data space. */
	shmdata = ( unsigned char * ) shmat ( shmid, ( void * ) 0, 0 );
	if ( shmdata == ( unsigned char * )-1 ) {
		perror ( "shmat" );
		return 1;
	}

//	if(itsnew){
//	bzero(shmdata,SHMSZ); <<<<<<<<<<<<<<<<<<<<<<<<<<IS SAFE???
//}

	return 0;
}

void* get_shm_addr ( size_t offset ) {
	return offset+shmdata;
}

int close_shm ( void ) {
	if ( shmdata==0 ) return 0;
	if ( shmdt ( shmdata ) ==-1 ) {
		perror ( "shmdt" );
		return 1;
	} else {
	  /* Destroy the segment */
  	if (shmctl(shmid, IPC_RMID, 0) == -1){
  	  perror("shmctl");
		return 1;
  	}
		return 0;
	}
}

int put_shm ( int code, size_t offset ) {
	if ( shmdata==0 ) return 1;
	memcpy ( shmdata+offset,&code,sizeof ( int ) );
//	memcpy ( shmdata+offset*sizeof ( int ),&code,sizeof ( int ) );
	return 0;
}

int get_shm ( int *code, size_t offset ) {
	if ( shmdata==0 ) return 1;
	memcpy ( code,shmdata+offset,sizeof ( int ) );
//	memcpy ( code,shmdata+offset*sizeof ( int ),sizeof ( int ) );
	return 0;
}


struct sockaddr_in  server;
int s,t;
char str[BUFSIZE];
//
int doconnect ( in_addr_t ip, int iport ) {
	if ( ( s=socket ( PF_INET,SOCK_STREAM,0 ) ) <0 ) {
		return -1;
	}
	memset ( ( char * ) &server, 0, sizeof ( server ) );
	server.sin_family = PF_INET;
	server.sin_addr.s_addr = ip;//inet_addr("127.0.0.1");
	server.sin_port = htons ( iport );
	if ( connect ( s, ( struct sockaddr * ) &server, sizeof ( server ) ) <0 ) {
		return -1;
	}
	return 0;
}
//
int doclose ( void ) {
	close ( s );
	return 0;
}
//
int dosend ( int size, char *img ) {
	int rc;
	int rsize;
	strcpy ( str,"put\n" );
	rc=send ( s, str, strlen ( str ),0 );
	if ( rc<0 ) return -1;
	t=recv ( s, str, BUFSIZ, 0 );
	if ( t<=0 ) return -1;
	str[t] = '\0';
	if ( strcmp ( str,"gimme size" ) !=0 ) return -2;
	sprintf ( str,"%d\n",size );
	rc=send ( s, str, strlen ( str ),0 );
	if ( rc<0 ) return -1;
	rc=send ( s, img, size, 0 );
	if ( rc<0 ) return -1;
	t=recv ( s, str, BUFSIZ, 0 );// recv size
	if ( t<=0 ) return -1;
	str[t] = '\0';
	rsize=atoi ( str );
	if ( rsize!=size ) return -3;
	return 0;
}
int domd5 ( char *md5 ) {
	int rc;
	strcpy ( str,"md5\n" );
	rc=send ( s, str, strlen ( str ),0 );
	if ( rc<0 ) return -1;
	t=recv ( s, md5, BUFSIZ, 0 );
	if ( t<=0 ) return -1;
	md5[t]='\0';
	return 0;
}
//
int recvsize ( int *size ) {
	int rc;
	strcpy ( str,"getsize\n" );
	rc=send ( s, str, strlen ( str ),0 );
	if ( rc<0 ) return -1;
	t=recv ( s, str, BUFSIZ, 0 );
	if ( t<=0 ) return -1;
	str[t]='\0';
	*size=atoi ( str );
	return 0;
}
//
int recvimg ( int size, char *img ) {
	int recvd;

	int n;
	time_t t0,t1;
	recvd=0;
	time ( &t0 );
	do {
		n=recv ( s,img+recvd,BUFSIZE,0 );
		if ( n>0 ) {
			recvd+=n;
			//      printf("%d of %d\n",recvd,len);
		} else {
//      if(n<0) perror("recvimg");
			return -1;
		}
	} while ( recvd<size );
	time ( &t1 );
//  printf("%d received in %d s\n",recvd,(int)(t1-t0));
	return recvd;
}
//

//
/*
int client ( int argc, char *argv[] )
{
	FILE *f;
	int put=0,fs,i;
	char *img=0;
	time_t t0,t1;
	int mkimg;
	char md5[64];

	if ( argc!=1 )
	{
		f=fopen ( argv[1],"r" );
		if ( f==0 )
		{
			perror ( "fopen" );
			exit ( 1 );
		}
		fseek ( f,0,SEEK_END );
		fs=ftell ( f );
		printf ( "file=%s, size=%d\n",argv[1],fs );
		rewind ( f );
		img= ( char * ) calloc ( fs,1 );
		if ( fread ( img,fs,1,f ) !=1 )
		{
			perror ( "fread" );
			exit ( 1 );
		}
		fclose ( f );
		mkimg=0;
	}
	else
	{
		mkimg=1;
	}

	while ( printf ( "\n> " ),fgets ( str,BUFSIZ,stdin ),!feof ( stdin ) )
	{
		if ( send ( s, str, strlen ( str ), 0 ) < 0 )
		{
			perror ( "send" );
			exit ( 1 );
		}
		if ( put==1 )
		{
			fs=atoi ( str );
			if ( mkimg==1 )
			{
				if ( img!=0 ) free ( img );
				img= ( char * ) calloc ( fs,1 );
				for ( i=0;i<fs;i++ )
				{
					img[i]= ( char ) ( i%256 );
				}
			}
			printf ( "sending img of %d byte\n",fs );
			MD5Data ( img,fs,md5 );
			printf ( "md5: %s\n",md5 );
			time ( &t0 );
			if ( send ( s, img, fs, 0 ) <0 )
			{
				perror ( "send img" );
				exit ( 1 );
			}
			time ( &t1 );
			printf ( "%d send in %d s\n",fs, ( int ) ( t1-t0 ) );
			put=0;
		}
		if ( ( t=recv ( s, str, BUFSIZ, 0 ) ) > 0 )
		{
			str[t] = '\0';
			printf ( "%d < %s", t,str );
			if ( strcmp ( str,"gimme size" ) ==0 )
			{
				printf ( "\nentering put mode\n" );
				put=1;
			}
		}
		else
		{
			if ( t < 0 )
			{
				perror ( "recv" );
			}
			else
			{
				printf ( "Server connection closed\n" );
			}
			exit ( 1 );
		}
	}
	exit ( 0 );
}
*/
/*
  struct hostent     *srvhost;
  struct sockaddr_in  server;
  u_long              srvaddr;

  srvaddr = inet_addr(hostname);
  srvhost = gethostbyaddr((char *)&srvaddr, sizeof(srvaddr), PF_INET);
  if (srvhost == NULL) {
  srvhost = gethostbyname(hostname);
  if (srvhost == NULL){
  fprintf(stderr,"Could not get IP Address\n");
  exit(1);
  }
  }
  srvaddr = *((unsigned long *)((srvhost->h_addr_list)[0]));
  memset((char *)&server, 0, sizeof(server));
  server.sin_family = PF_INET;
  server.sin_addr.s_addr = srvaddr;
  server.sin_port = htons(9999);
  connect(s, (struct sockaddr *) &server, sizeof(server));
*/
